#include "ConfigManager.hpp"
#include <filesystem>
#include <iostream>

ConfigManager& ConfigManager::getInstance() {
    static ConfigManager instance;
    return instance;
}

bool ConfigManager::init(const std::string& env) {
    // 首先加载默认配置
    if (!loadConfig(configDir_ + "/default.yaml")) {
        std::cerr << "Failed to load default config" << std::endl;
        return false;
    }

    // 如果指定了环境，加载对应的环境配置
    if (env != "default") {
        std::string envConfig = configDir_ + "/" + env + ".yaml";
        if (std::filesystem::exists(envConfig)) {
            YAML::Node envNode = YAML::LoadFile(envConfig);
            config_ = mergeConfig(config_, envNode);
        }
    }

    return true;
}

bool ConfigManager::loadConfig(const std::string& filename) {
    try {
        config_ = YAML::LoadFile(filename);
        return true;
    } catch (const YAML::Exception& e) {
        std::cerr << "Error loading config file: " << filename << std::endl;
        std::cerr << "Error: " << e.what() << std::endl;
        return false;
    }
}

std::string ConfigManager::resolveKey(const std::string& key) const {
    return key;
}

YAML::Node ConfigManager::getNode(const std::string& key) const {
    try {
        std::string resolvedKey = resolveKey(key);
        return config_[resolvedKey];
    } catch (const YAML::Exception& e) {
        return YAML::Node();
    }
}

template<typename T>
T ConfigManager::get(const std::string& key, const T& defaultValue) const {
    try {
        YAML::Node node = getNode(key);
        if (node && !node.IsNull()) {
            return node.as<T>();
        }
    } catch (const YAML::Exception& e) {
        std::cerr << "Error getting config value for key: " << key << std::endl;
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return defaultValue;
}

// 显式实例化常用类型
template int ConfigManager::get<int>(const std::string&, const int&) const;
template double ConfigManager::get<double>(const std::string&, const double&) const;
template std::string ConfigManager::get<std::string>(const std::string&, const std::string&) const;
template bool ConfigManager::get<bool>(const std::string&, const bool&) const; 